package com.espirit.eap.util;

import java.io.InputStream;
import java.lang.reflect.Method;

import javax.annotation.Resource;
import javax.servlet.ServletContext;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.espirit.eap.manager.SystemDataService;
import com.espirit.eap.sa.LoginUserService;
import com.espirit.eap.sa.WebsiteService;
import com.googlecode.cswish.Config;
import com.googlecode.cswish.security.UserTracerService;
import com.googlecode.cswish.struts.IAsync;
import com.googlecode.cswish.struts.IStartupManager;
import com.googlecode.cswish.struts.hibernate.DynamicClassLoaderFactory;
import com.googlecode.cswish.struts.hibernate.DynamicModelManager;
import com.googlecode.cswish.struts.interceptor.ExceptionMappingInterceptor;
import com.googlecode.cswish.struts.spring.ObjectFactory;
import com.googlecode.cswish.struts.spring.SystemEnv;

/**
 * It's a key class, the core content load from encrypt data
 * 
 * @author jerry.feng Date 2009-10-1
 *
 */
@Service
@Lazy(value=false)
public class CoreStartupManager implements IStartupManager, IAsync {

	private static final Logger logger = Logger.getLogger(CoreStartupManager.class);
	
	@Resource
	private DynamicClassLoaderFactory dynamicClassLoaderFactory;
	
	@Resource
	private UserTracerService userTracerService;
	
	@Resource
    private ObjectFactory objectFactory;
	
	@Resource
    private Config config;
	
	@Resource
	private DynamicModelManager dynamicModelManager;
	
	private long expiredTime;
	
	@Override
	public void startup(ServletContext servletContext) {
		boolean isJunitTest = "true".equals(System.getProperty(SystemEnv.JUNIT_TEST));
		if (isJunitTest) {
			return ;
		}
		
		dynamicModelManager.enableCrossSite();
		IAsync asyncStartup = (IAsync)objectFactory.getBean(CoreStartupManager.class.getName(), true);
		asyncStartup.asyncExecute(servletContext);
	}
	
	@Async
	public void asyncExecute(Object parameter) {
		ServletContext servletContext = (ServletContext)parameter;
		try {
			// load the core class
			InputStream input = this.getClass().getResourceAsStream("/com/espirit/eap/util/EapStartupManager");
			Class clazz = null;
			if (input != null) {
				clazz = dynamicClassLoaderFactory.defineClass("com.espirit.eap.util.EapStartupManagerPlugin", input);
			} else if ("true".equals(System.getProperty(SystemEnv.RUNNING_IN_ECLIPSE))) {
				clazz = Class.forName("com.espirit.eap.util.EapStartupManagerPlugin");
			}
			IOUtils.closeQuietly(input);
			
			// find method & build instance
			Method[] methods = clazz.getDeclaredMethods();
			Method executeMethod = null;
			for (Method method : methods) {
				if ("execute".equals(method.getName())) {
					executeMethod = method;
					break;
				}
			}
			Object instance = clazz.newInstance();
		
			LoginUserService userService = objectFactory.getBean(LoginUserService.class, true);
		    SystemDataService systemDataService = objectFactory.getBean(SystemDataService.class, true);
		    WebsiteService websiteService = objectFactory.getBean(WebsiteService.class, true);
			// run it
			executeMethod.invoke(instance, this, userTracerService, config, userService, systemDataService, websiteService
					, servletContext);
			
			// check expired time
			new Thread(new Runnable() {
				@Override
				public void run() {
					while (true) {
						try {
							// check license each 5 minutes, and 5 minutes is enough for the EapStartupManagerPlugin startup
							Thread.sleep(60000 * 5);
							
							if (expiredTime == 0) {
								return;
							} else {
								if (System.currentTimeMillis() > expiredTime) {
									ExceptionMappingInterceptor.interceptorEx = "error.licenseExpired";
								}
							}
						} catch (InterruptedException e) {
							break;
						}
					}
				}
			}).start();
		} catch (Exception ex) {
			boolean isEclipseEnv = "true".equals(System.getProperty(SystemEnv.RUNNING_IN_ECLIPSE));
			if (isEclipseEnv) {
				logger.error("Can't startup plugin", ex);
			} else {
				logger.error("Can't startup plugin");
			}
			ExceptionMappingInterceptor.interceptorEx = "error.licenseExpired";
		}
	}
	
	public void setExpiredTime(long expiredTime) {
		this.expiredTime = expiredTime;
	}
}